home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / macros.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  11KB  |  571 lines

  1. /* --------------------------------- macros.c ------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Handle keyboard macros.
  8.  *
  9.  * This module manages the input data stream. KeysBuffer hold keystrokes that
  10.  * are processed before the keyboard device is interrogated for more. It is
  11.  * filled with data by calling mac_key().
  12.  * Another subject is key macros. Some keys are bound to a definition which
  13.  * is a list of keystokes. When such a character is encountered it is this
  14.  * list that gets placed in the KeysBuffer.
  15. */
  16.  
  17. #include "fly.h"
  18.  
  19.  
  20. #define KEYSBUFFERSIZE    1024
  21. #define KEYSBUFFEREND    (KeysBuffer+KEYSBUFFERSIZE)
  22. #define RECBUFFERSIZE    1024
  23.  
  24. static Ushort    *KeysBuffer = 0;    /* circular buffer control */
  25. static Ushort    *KeysHead = 0;
  26. static Ushort    *KeysTail = 0;
  27. static int    KeysCount = 0;
  28. static Ushort    *RecordBuffer = 0;    /* macro recording buffer */
  29. static Ushort    *RecordPtr = 0;        /* position in RecordBuffer */
  30. static int    Quoting = 0;        /* mread ignores special keys */
  31. static MACRO    *Macros = 0;        /* macro definitions */
  32. static MACRO    *Recording = 0;        /* Macro being recorded */
  33. static HMSG    *RecordingMsg = 0;
  34.  
  35. LOCAL_FUNC int    NEAR record_char (int ch);
  36. LOCAL_FUNC int    NEAR mac_expand (int name);
  37. LOCAL_FUNC int    NEAR mac_hot (int name);
  38. LOCAL_FUNC int    NEAR mac_key (int key);
  39. LOCAL_FUNC int    NEAR mac_record (void);
  40. LOCAL_FUNC int    NEAR mac_play (void);
  41. LOCAL_FUNC int    NEAR mac_write (void);
  42. LOCAL_FUNC int    NEAR mac_read (void);
  43.  
  44. extern int FAR
  45. mread (void)                /* non-blocking read */
  46. {
  47.     int    ch;
  48.  
  49. ReRead:
  50.     if (KeysCount > 0) {
  51.         --KeysCount;
  52.         ch = (int)*KeysHead++;
  53.         if (KeysHead == KEYSBUFFEREND)
  54.             KeysHead = KeysBuffer;
  55.     } else {
  56.         for (;;) {
  57.             ch = Kbd->Read ();
  58.             if (-1 != ch && Recording) {
  59.                 ch = record_char (ch);
  60.                 if (ch == -1)
  61.                     continue;
  62.             }
  63.             break;
  64.         }
  65.     }
  66.  
  67.     if (ch != -1) {
  68.         if (mac_hot (ch))
  69.             goto ReRead;
  70.  
  71.     }
  72.  
  73.     if (!Quoting) {
  74.         if (KF_MACRECORD == ch) {
  75.             mac_record ();
  76.             goto ReRead;
  77.         }
  78.  
  79.         if (KF_MACPLAY == ch) {
  80.             mac_play ();
  81.             goto ReRead;
  82.         }
  83.     }
  84.  
  85.     return (ch);
  86. }
  87.  
  88. extern int FAR
  89. mgetch (void)                /* blocking read */
  90. {
  91.     int    ch;
  92.  
  93.     while (-1 == (ch = mread ()))
  94.         sys_poll (1);
  95.     return (ch);
  96. }
  97.  
  98. extern int FAR
  99. mac_interpret (Ushort *keys, int len)
  100. {
  101.     int    key;
  102.  
  103.     while (len-- > 0) {
  104.         key = (int)*keys++;
  105.         if (mac_hot (key))
  106.             continue;
  107.         if (KF_MACPLAY == key) {
  108.             if (len-- <= 0)
  109.                 return (1);
  110.             if (mac_expand ((int)*keys++))
  111.                 continue;
  112.             MsgPrintf (10, "Macro undefined");
  113.         }
  114.         if (mac_key (key))
  115.             return (1);
  116.     }
  117.     return (0);
  118. }
  119.  
  120. extern void FAR
  121. mac_flush (void)
  122. {
  123.     KeysHead = KeysTail = KeysBuffer;
  124.     KeysCount = 0;
  125.     Recording = 0;
  126. }
  127.  
  128. extern int FAR
  129. mac_init (void)
  130. {
  131.     int    i;
  132.     MACRO    *m;
  133.  
  134.     KeysBuffer = (Ushort *)memory_calloc (KEYSBUFFERSIZE,
  135.                         sizeof (*KeysBuffer));
  136.     if (!KeysBuffer) {
  137.         MsgEPrintf (-50, "macros: no mem (1)");
  138.         return (1);
  139.     }
  140.     RecordBuffer = (Ushort *)memory_calloc (RECBUFFERSIZE,
  141.                         sizeof (*RecordBuffer));
  142.     if (!RecordBuffer) {
  143.         MsgEPrintf (-50, "macros: no mem (2)");
  144.         return (1);
  145.     }
  146.  
  147.     mac_flush ();
  148.  
  149.     Macros = (MACRO *)memory_calloc (st.nMacros, sizeof (*Macros));
  150.     if (!Macros) {
  151.         MsgEPrintf (-50, "macros: no mem (3)");
  152.         return (1);
  153.     }
  154.  
  155.     for (m = Macros, i = 0; i < st.nMacros; ++i, ++m) {
  156.         m->name = KEYUNUSED;
  157.         m->len  = 0;
  158.         m->def  = 0;
  159.     }
  160.  
  161.     mac_read ();
  162.  
  163.     return (0);
  164. }
  165.  
  166. extern void FAR
  167. mac_term (void)
  168. {
  169.     int    i, j;
  170.     MACRO    *m;
  171.  
  172.     mac_flush ();
  173.     KeysHead = KeysTail = 0;
  174.  
  175.     KeysBuffer = memory_cfree (KeysBuffer, KEYSBUFFERSIZE,
  176.                         sizeof (*KeysBuffer));
  177.     RecordBuffer = memory_cfree (RecordBuffer, RECBUFFERSIZE,
  178.                         sizeof (*RecordBuffer));
  179.  
  180.     if (Macros) {
  181.         mac_write ();
  182.  
  183.         for (m = Macros, j = i = 0; i < st.nMacros; ++i, ++m) {
  184.             if (KEYUNUSED != m->name) {
  185.                 m->def  = memory_cfree (m->def,
  186.                         m->len, sizeof (*m->def));
  187.                 m->name = KEYUNUSED;
  188.                 m->len  = 0;
  189.                 ++j;
  190.             }
  191.         }
  192.  
  193.         Macros = memory_cfree (Macros, st.nMacros, sizeof (*Macros));
  194.         LogPrintf ("nMacros  %d\n", j);
  195.     }
  196. }
  197.  
  198. LOCAL_FUNC int NEAR
  199. mac_key (int key)
  200. {
  201.     if (KeysBuffer && KeysCount < KEYSBUFFERSIZE) {
  202.         ++KeysCount;
  203.         *KeysTail++ = (Ushort)key;
  204.         if (KeysTail == KEYSBUFFEREND)
  205.             KeysTail = KeysBuffer;
  206.         return (0);
  207.     } else
  208.         return (1);
  209. }
  210.  
  211. LOCAL_FUNC MACRO * NEAR
  212. mac_find (int name)
  213. {
  214.     int    i;
  215.     MACRO    *m;
  216.  
  217.     if (!Macros)
  218.         return (0);
  219.  
  220.     for (m = Macros, i = 0; i < st.nMacros; ++i, ++m)
  221.         if (m->name == (Ushort)name)
  222.             return (m);
  223.     return (0);
  224. }
  225.  
  226. LOCAL_FUNC void NEAR
  227. record_add (int ch)
  228. {
  229.     if (!RecordBuffer)
  230.         MsgEPrintf (50, "No Recording");
  231.     else if (RecordPtr == RecordBuffer+RECBUFFERSIZE)
  232.         MsgEPrintf (50, "Recording overflow");
  233.     else
  234.         *RecordPtr++ = (Ushort)ch;
  235. }
  236.  
  237. LOCAL_FUNC int NEAR
  238. record_char (int ch)
  239. /*
  240.  * return (-1): control char used up, re-read.
  241.  * else        use this char.
  242. */
  243. {
  244.     MACRO    *m;
  245.     int    new, l;
  246.     HMSG    *p;
  247.  
  248.     if (ch == KF_MACPLAY) {
  249.         m = Recording;
  250.         Recording = 0;
  251.  
  252.         p = MsgWPrintf (0, "Abort/Cont/Quote?");
  253.         ch = mgetch ();
  254.         msg_del (p);
  255.         if (ch == KF_MACPLAY) {            /* abort */
  256.             if (m->def == 0)
  257.                 m->name = KEYUNUSED;
  258.             MsgPrintf (50, "Macro aborted");
  259.             msg_del (RecordingMsg);
  260.             --Quoting;
  261.             return (-1);
  262.         } else if (ch == KF_MACRECORD) {    /* cont */
  263.             Recording = m;
  264.             return (-1);
  265.         }
  266.         Recording = m;
  267.         record_add (KF_MACPLAY);
  268.         record_add (ch);
  269.         if (!mac_expand (ch)) {
  270.             MsgPrintf (10, "Macro undefined");
  271.             return (ch);
  272.         }
  273.         return (-1);
  274.     } else if (ch == KF_MACRECORD) {
  275.         msg_del (RecordingMsg);
  276.         RecordingMsg = 0;
  277.         --Quoting;
  278.  
  279.         m = Recording;
  280.         Recording = 0;
  281.  
  282.         new = (m->def == 0);
  283.         l = RecordPtr - RecordBuffer;
  284.  
  285.         if (new && !l) {            /* aborted */
  286.             MsgPrintf (50, "Macro aborted");
  287.             m->name = KEYUNUSED;
  288.             return (-1);
  289.         }
  290.         m->len = 0;
  291.         if (!new)                /* delete old */
  292.             m->def = memory_cfree (m->def,
  293.                         m->len, sizeof (*m->def));
  294.  
  295.         if (!l) {                /* just deleting */
  296.             MsgPrintf (50, "Macro deleted");
  297.             m->name = KEYUNUSED;
  298.             return (-1);
  299.         }
  300.  
  301.         m->def = (Ushort *)memory_calloc (l, sizeof (*m->def));
  302.         if (!m->def) {
  303.             MsgPrintf (100, "macros: no mem (4)");
  304.             m->name = KEYUNUSED;
  305.             return (-1);
  306.         }
  307.         memcpy (m->def, RecordBuffer, l * sizeof (Ushort));
  308.         m->len = (Ushort)l;
  309.  
  310.         MsgPrintf (50, "Macro %sdefined", new ? "" : "re");
  311.         return (-1);
  312.     }
  313.  
  314.     record_add (ch);
  315.     return (ch);
  316. }
  317.  
  318. LOCAL_FUNC int NEAR
  319. mac_record (void)
  320. {
  321.     int    name;
  322.     MACRO    *m;
  323.     HMSG    *p;
  324.  
  325.     if (!Macros || !RecordBuffer) {
  326.         MsgPrintf (50, "No Macros");
  327.         return (-1);
  328.     }
  329.  
  330.     p = MsgWPrintf (0, "Macro Key ?");
  331.     name = Kbd->Getch ();            /* get macro name */
  332.     msg_del (p);
  333.     if (name == KF_MACRECORD || name == KF_MACPLAY) {
  334.         MsgPrintf (50, "Macro aborted");
  335.         return (0);
  336.     }
  337.  
  338.     m = mac_find (name);
  339.     if (!m) {
  340.         m = mac_find (KEYUNUSED);        /* new macro */
  341.         if (!m) {
  342.             MsgWPrintf (100, "All macros used");
  343.             return (1);        /* all macros defined */
  344.         }
  345.         m->name = (Ushort)name;
  346.         m->len = 0;
  347.         m->def = 0;
  348.     } else
  349.         MsgWPrintf (100, "Warn ReDefining");
  350.  
  351.     Recording = m;
  352.     RecordPtr = RecordBuffer;
  353.     RecordingMsg = MsgWPrintf (0, "Recording...");
  354.     ++Quoting;
  355.  
  356.     return (0);
  357. }
  358.  
  359. /* return 1 if hot (and then expand it too).
  360. */
  361. LOCAL_FUNC int NEAR
  362. mac_hot (int name)
  363. {
  364.     int    r, s;
  365.  
  366.     r = name & K_RAW;
  367.     s = name & K_SHIFTS;
  368.     if (((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9'))
  369.         && (K_CTRL == s || K_ALT == s || (K_BTN & s))) {
  370.         if (mac_expand (name))
  371.             return (1);
  372.     }
  373.     return (0);
  374. }
  375.  
  376. /* return 1 if a macro (and then expand it too).
  377. */
  378. LOCAL_FUNC int NEAR
  379. mac_expand (int name)
  380. {
  381.     MACRO        *m;
  382.     static int    depth = 0;
  383.  
  384.     m = mac_find (name);
  385.     if (!m || !m->def)
  386.         return (0);
  387.  
  388.     if (depth > 16) {
  389.         MsgEPrintf (10, "Macro nesting > 16");
  390.         return (1);
  391.     }
  392.     ++depth;
  393.     mac_interpret (m->def, (int)m->len);
  394.     --depth;
  395.  
  396.     return (1);
  397. }
  398.  
  399. LOCAL_FUNC int NEAR
  400. mac_play (void)
  401. {
  402.     int    name;
  403.     HMSG    *p;
  404.  
  405.     if (!Macros || !RecordBuffer) {
  406.         MsgPrintf (100, "No Macros");
  407.         return (-1);
  408.     }
  409.  
  410.     p = MsgWPrintf (0, "Play/Abort?");
  411.     ++Quoting;
  412.     name = mgetch ();            /* get macro name */
  413.     --Quoting;
  414.     msg_del (p);
  415.     if (name == KF_MACRECORD || name == KF_MACPLAY) {
  416.         MsgPrintf (100, "Macro aborted");
  417.         return (-1);
  418.     }
  419.  
  420.     if (mac_expand (name))            /* play */
  421.         return (0);
  422.  
  423.     MsgPrintf (10, "Macro undefined");
  424.     return (-1);
  425. }
  426.  
  427. LOCAL_FUNC int NEAR
  428. write_short (Ushort n, FILE *f)
  429. {
  430.     fputc (0x0ff&(n>>8), f);
  431.     if (ferror (f))
  432.         return (0);
  433.     fputc (0x0ff&n, f);
  434.     if (ferror (f))
  435.         return (1);
  436.     return (2);
  437. }
  438.  
  439. LOCAL_FUNC int NEAR
  440. read_short (int *i, FILE *f)
  441. {
  442.     int    n;
  443.  
  444.     n = fgetc (f);
  445.     if (ferror (f) || feof (f))
  446.         return (0);
  447.     n = (n<<8) + fgetc (f);
  448.     if (ferror (f) || feof (f))
  449.         return (1);
  450.     *i = n;
  451.     return (2);
  452. }
  453.  
  454. LOCAL_FUNC int NEAR
  455. mac_write (void)
  456. {
  457.     int    i;
  458.     Ushort    j;
  459.     MACRO    *m;
  460.     FILE    *mac;
  461.  
  462.     if (!Macros || !st.mname)
  463.         return (1);
  464.  
  465.     Sys->BuildFileName (st.filename, st.fdir, st.mname, MAC_EXT);
  466.     mac = fopen (st.filename, WBMODE);
  467.     if (!mac) {
  468. #if 1
  469.         MsgEPrintf (-50, "macros: open %s failed (1)", st.filename);
  470. #endif
  471.         return (1);
  472.     }
  473.  
  474.     for (m = Macros, i = 0; i < st.nMacros; ++i, ++m) {
  475.         if (!m->def)
  476.             continue;
  477.         if (2 != write_short (m->name, mac)) {
  478.             MsgEPrintf (-50, "macros: write %s failed (1)",
  479.                 st.filename);
  480.             goto ret;
  481.         }
  482.         if (2 != write_short (m->len, mac)) {
  483.             MsgEPrintf (-50, "macros: write %s failed (2)",
  484.                 st.filename);
  485.             goto ret;
  486.         }
  487.         for (j = 0; j < m->len; ++j) {
  488.             if (2 != write_short (m->def[j], mac)) {
  489.                 MsgEPrintf (-50, "macros: write %s failed (3)",
  490.                     st.filename);
  491.                 goto ret;
  492.             }
  493.         }
  494.     }
  495. ret:
  496.     fclose (mac);
  497.     return (0);
  498. }
  499.  
  500. LOCAL_FUNC int NEAR
  501. mac_read (void)
  502. {
  503.     int    i, t;
  504.     Ushort    j;
  505.     MACRO    *m;
  506.     FILE    *mac;
  507.  
  508.     if (!st.mname)
  509.         st.mname = STRdup ("fly");
  510.  
  511.     if (!Macros || !st.mname) {
  512.         MsgPrintf (-50, "No Macros");
  513.         return (1);
  514.     }
  515.  
  516.     i = max_read (Macros);
  517.     if (i >= 0)
  518.         return (i);
  519.  
  520.     Sys->BuildFileName (st.filename, st.fdir, st.mname, MAC_EXT);
  521.     mac = fopen (st.filename, RBMODE);
  522.     if (!mac) {
  523.         MsgEPrintf (-50, "macros: open %s failed (2)", st.filename);
  524.         return (1);
  525.     }
  526.     LogPrintf ("Macros   %s\n", st.filename);
  527.  
  528.     for (i = 0, m = Macros;; ++i, ++m) {
  529.         if (2 != read_short (&t, mac))
  530.             break;
  531.         if (i >= st.nMacros) {
  532.             MsgEPrintf (-50, "too many macros");
  533.             goto ret;
  534.         }
  535.         m->name = (Ushort)t;
  536.         if (2 != read_short (&t, mac)) {
  537.             MsgEPrintf (-50, "macros: read %s failed (1)",
  538.                 st.filename);
  539.             m->name = KEYUNUSED;
  540.             goto ret;
  541.         }
  542.         m->len = (Ushort)t;
  543.         m->def = (Ushort *)memory_calloc (m->len, sizeof (*m->def));
  544.         if (!m->def) {
  545.             MsgPrintf (-50, "macros: no mem (5)");
  546.             m->name = KEYUNUSED;
  547.             goto ret;
  548.         }
  549.         for (j = 0; j < m->len; ++j) {
  550.             if (2 != read_short (&t, mac)) {
  551.                 MsgEPrintf (-50, "macros: read %s failed (2)",
  552.                     st.filename);
  553.                 m->name = KEYUNUSED;
  554.                 m->def = memory_cfree (m->def,
  555.                         m->len, sizeof (*m->def));
  556.                 goto ret;
  557.             }
  558.             m->def[j] = (Ushort)t;
  559.         }
  560.     }
  561.     if (!feof (mac))
  562.         MsgEPrintf (-50, "read %s failed (3)", st.filename);
  563. ret:
  564.     fclose (mac);
  565.     return (0);
  566. }
  567.  
  568. #undef KEYSBUFFERSIZE
  569. #undef KEYSBUFFEREND
  570. #undef RECBUFFERSIZE
  571.